import React, { useEffect, useState } from 'react';
import {
  Badge,
  Button,
  Card, Collapse, Drawer, Form, Grid, Input,
  Notification,
  PaginationProps,
  Select,
  Space,
  Table, Tag, TreeSelect
} from '@arco-design/web-react';
import { IconDelete, IconPlus, IconRefresh, IconSearch } from '@arco-design/web-react/icon';
import useLocale from '@/utils/useLocale';
import instance from '@/utils/request';
import {
  EnabledOptions,
  ParameterAbilityOptions,
  ParameterDataTypeOptions,
  ParameterValueTypeOptions
} from '@/constants/options';
import { EditMode } from '@/constants/enums';
import { convertToSelectOptions, resolveEnabledName } from '@/constants/functions';
import { defaultDrawerLayout, defaultDrawerWidth, defaultPaginationProps } from '@/constants/defaults';
import { ModelResponse, ParameterResponse } from '@/constants/type';
import { TableOperationButtonGroup } from '@/components/common/table_operation_button_group';

const { Row } = Grid;
const locale = {
  'en-US': {},
  'zh-CN': {
    'title.create': '创建物模型',
    'title.update': '修改物模型',

    'label.name': '物模型名称',
    'label.code': '物模型编码',
    'label.dataType': '数据类型',
    'label.valueType': '值类型',
    'label.parameter.public': '关联公共参数',
    'label.parameter.public.placeholder': '请选择关联公共参数',
    'label.parameter.private': '关联私有参数',
    'label.parameter.private.add': '创建私有参数',
    'label.parameter.private.placeholder': '请选择关联私有参数',
    'label.parameter.name': '参数名称',
    'label.parameter.name.placeholder': '请输入参数名称',
    'label.parameter.code': '参数编码',
    'label.parameter.code.placeholder': '请输入参数编码',
    'label.parameter.dataType': '数据类型',
    'label.parameter.dataType.placeholder': '请选择数据类型',
    'label.parameter.valueType': '值类型',
    'label.parameter.abilities': '能力',
    'label.parameter.abilities.placeholder': '请输入参数能力',
    'label.parameter.unit': '单位',
    'label.parameter.unit.placeholder': '请输入物模型单位',
    'label.parameter.valueType.placeholder': '请选择值类型',
    'label.enabled': '状态',
    'label.parentId': '父级物模型',
    'label.remark': '备注',

    'placeholder.id': '请输入物模型ID',
    'placeholder.name': '请输入物模型名称',
    'placeholder.code': '请输入物模型编码',
    'placeholder.type': '请选择物模型类型',
    'placeholder.parentId': '请选择物模型',
    'placeholder.remark': '请输入备注',
    'placeholder.enabled': '请选择物模型状态',

    'columns.id': 'ID',
    'columns.name': '物模型名称',
    'columns.code': '物模型编码',
    'columns.dataType': '数据类型',
    'columns.valueType': '值类型',
    'columns.parameters.public': '公共参数',
    'columns.parameters.private': '私有参数',
    'columns.parentId': '父级物模型',
    'columns.remark': '物模型备注',
    'columns.enabled': '状态',
    'columns.operations': '操作',

    'button.search': '搜索',
    'button.reset': '重置',
    'button.create': '创建',
    'button.update': '编辑',
    'button.delete': '删除',
    'button.upload': '批量导入',
    'button.download': '下载物模型'
  }
};

const SearchForm = (props: {
  onSubmit: ({}) => void,
  onReset: () => void,
}) => {
  const t = useLocale(locale);
  const [form] = Form.useForm();
  return (
    <Form form={form} style={{ padding: '1rem', background: 'white' }}>
      <Row style={{ display: 'flex' }}>
        <Grid style={{ flexGrow: '1' }} cols={4} colGap={12} rowGap={16}>
          <Grid.GridItem>
            <Form.Item noStyle label={t['columns.id']} field="id">
              <Input placeholder={t['placeholder.id']} allowClear />
            </Form.Item>
          </Grid.GridItem>
          <Grid.GridItem>
            <Form.Item noStyle label={t['columns.name']} field="name">
              <Input allowClear placeholder={t['placeholder.name']} />
            </Form.Item>
          </Grid.GridItem>
          <Grid.GridItem>
            <Form.Item noStyle label={t['columns.remark']} field="remark">
              <Input allowClear placeholder={t['placeholder.remark']} />
            </Form.Item>
          </Grid.GridItem>
          <Grid.GridItem>
            <Form.Item noStyle label={t['columns.enabled']} field="enabled">
              <Select
                placeholder={t['placeholder.enabled']}
                options={EnabledOptions}
                allowClear
              />
            </Form.Item>
          </Grid.GridItem>
        </Grid>
        <Row style={{ display: 'inline-flex', marginLeft: '1rem' }} justify={'center'}>
          <Space direction={'vertical'}>
            <Button type="primary" icon={<IconSearch />} onClick={() => props.onSubmit(form.getFieldsValue())}>
              {t['button.search']}
            </Button>
            <Button icon={<IconRefresh />} onClick={() => {
              form.resetFields();
              props.onReset();
            }}>
              {t['button.reset']}
            </Button>
          </Space>
        </Row>
      </Row>
    </Form>
  );
};

const ModelDrawer = (props: {
  record?: ModelResponse;
  visible: boolean;
  toggleVisible: (v: boolean) => void;
  mode: EditMode;
  onFinish: () => void;
}) => {
  const t = useLocale(locale);
  const [form] = Form.useForm();
  const [confirmLoading, setConfirmLoading] = useState(false);
  const [parameterData, setParameterData] = useState([]);
  const [parameterTreeData, setParameterTreeData] = useState([]);
  const [parentIdOptions, setParentIdOptions] = useState([]);
  const title = () => {
    switch (props.mode) {
      case EditMode.Create:
        return t['title.create'];
      case EditMode.Update:
        return t['title.update'];
      default:
        return '';
    }
  };

  function onSubmitDrawer() {
    form.validate().then(() => {
      setConfirmLoading(true);
      const data = form.getFields();
      const ids = (form.getFieldValue('publicParameterIdList') || []);
      parameterData.filter(it => ids.includes(it.id)).forEach(it => data.parameters.push(it));
      instance
        .post(props.mode === EditMode.Create ? '/api/model/create' : '/api/model/update', data)
        .then((res) => {
          if (res.data.code === 200) {
            // 刷新页面数据
            Notification.success({
              title: res.data.message,
              content: ''
            });
            props.onFinish();
          } else {
            Notification.error({
              title: res.data.message,
              content: res.data.data
            });
          }
        })
        .finally(() => {
          form.resetFields();
          setConfirmLoading(false);
          props.toggleVisible(false);
        });
    });
  }

  function onCancelDrawer() {
    props.toggleVisible(false);
  }

  function fetchRoleTreeData() {
    instance
      .post('/api/parameter/list', { query: { common: true } })
      .then((res) => {
        if (res.data.code === 200) {
          setParameterData(res.data.data);
          setParameterTreeData(convertToSelectOptions(res.data.data));
        }
      });
  }

  function fillFormData() {
    form.resetFields();
    switch (props.mode) {
      case EditMode.Update:
        // 如果是更新模式，根据parentId查询父节点的信息
        if (!!props.record?.parentId) {
          instance
            .post('/api/model/get', { id: props.record.parentId })
            .then((res) => {
              if (res.data.code === 200) {
                setParentIdOptions([{
                  label: res.data.data.name,
                  value: res.data.data.id
                }]);
                form.setFieldValue('parentId', props.record?.parentId || null);
              } else {
                setParentIdOptions(['未知']);
              }
            });
        }
        form.setFieldsValue(props.record);
        form.setFieldValue('enabled', props.record?.enabled + '' || 'false');
        form.setFieldValue('publicParameterIdList', props.record?.parameters?.filter(it => !!it.common).map(it => it.id) || []);
        form.setFieldValue('parameters', props.record?.parameters?.filter(it => !!!it.common) || []);
        break;
      case EditMode.Create:
        // 如果是创建模式，record则作为父节点的信息
        if (!!props.record?.name && !!props.record?.id) {
          setParentIdOptions([{
            label: props.record.name,
            value: props.record.id
          }]);
          form.setFieldValue('parentId', props.record?.id || null);
        }
        form.setFieldValue('enabled', 'true');
        break;
    }
  }

  useEffect(() => {
    fetchRoleTreeData();
    fillFormData();
  }, [props.record, props.mode]);

  return (
    <Drawer
      width={defaultDrawerWidth}
      title={<span>{title()}</span>}
      visible={props.visible}
      confirmLoading={confirmLoading}
      onOk={onSubmitDrawer}
      onCancel={onCancelDrawer}
    >
      <Form {...defaultDrawerLayout} form={form} layout="vertical">
        <Form.Item label={t['label.name']} required field="name" rules={[{ required: true }]}>
          <Input placeholder={t['placeholder.name']} />
        </Form.Item>
        <Form.Item label={t['label.code']} required field="code" rules={[{ required: true }]}>
          <Input placeholder={t['placeholder.code']} />
        </Form.Item>
        <Form.Item label={t['label.parentId']} field="parentId" rules={[{ required: false }]}>
          <Select placeholder={t['placeholder.parentId']} disabled options={parentIdOptions} />
        </Form.Item>
        <Form.Item label={t['label.parameter.public']} field="publicParameterIdList">
          <TreeSelect placeholder={t['label.parameter.public.placeholder']} treeData={parameterTreeData}
                      treeCheckable />
        </Form.Item>
        <Form.Item label={t['label.parameter.private']}>
          <Collapse accordion>
            <Form.List noStyle rules={[{ required: false }]} field="parameters">
              {(fields, { add, remove }) => {
                return (
                  <div style={{ paddingBottom: '0px' }}>
                    {
                      fields.map((item, index) => {
                        return (
                          <Collapse.Item key={'parameter_new_' + index}
                                         header={!!form.getFieldValue(item.field) ? form.getFieldValue(item.field).name : '私有参数[新建]'}
                                         name={'item' + index}
                                         extra={<IconDelete onClick={() => remove(index)} />}>
                            <Form.Item label={t['label.parameter.name']} required field={item.field + '.name'}
                                       rules={[{ required: true }]}>
                              <Input placeholder={t['label.parameter.name.placeholder']} />
                            </Form.Item>
                            <Form.Item label={t['label.parameter.code']} required field={item.field + '.code'}
                                       rules={[{ required: true }]}>
                              <Input placeholder={t['label.parameter.code.placeholder']} />
                            </Form.Item>
                            <Form.Item label={t['label.parameter.dataType']} field={item.field + '.dataType'}
                                       rules={[{ required: true }]}>
                              <Select placeholder={t['label.parameter.dataType.placeholder']}
                                      options={ParameterDataTypeOptions} />
                            </Form.Item>
                            <Form.Item label={t['label.parameter.valueType']} field={item.field + '.valueType'}
                                       rules={[{ required: true }]}>
                              <Select placeholder={t['label.parameter.valueType.placeholder']}
                                      options={ParameterValueTypeOptions} />
                            </Form.Item>
                            <Form.Item label={t['label.parameter.abilities']} field={item.field + '.abilities'}
                                       rules={[{ required: false }]}>
                              <TreeSelect placeholder={t['label.parameter.abilities.placeholder']}
                                          treeData={ParameterAbilityOptions}
                                          fieldNames={{ key: 'value', title: 'label' }} treeCheckable />
                            </Form.Item>
                            <Form.Item label={t['label.parameter.unit']} field={item.field + '.unit'}
                                       rules={[{ required: false }]}>
                              <Input placeholder={t['label.parameter.unit.placeholder']} />
                            </Form.Item>
                          </Collapse.Item>
                        );
                      })
                    }
                    <Button icon={<IconPlus />} style={{ width: '100%' }}
                            onClick={() => add()}>{t['label.parameter.private.add']}</Button>
                  </div>
                );
              }}
            </Form.List>
          </Collapse>
        </Form.Item>
        <Form.Item label={t['label.enabled']} field="enabled" rules={[{ required: true }]}>
          <Select placeholder={t['placeholder.enabled']} options={EnabledOptions} />
        </Form.Item>
        <Form.Item label={t['label.remark']} field="remark" rules={[{ required: false }]}>
          <Input.TextArea placeholder={t['placeholder.remark']} />
        </Form.Item>
      </Form>
    </Drawer>
  );
};

const ModelPage = () => {
  const t = useLocale(locale);
  const [data, setData] = useState([]);
  const [pagination, setPagination] = useState<PaginationProps>(defaultPaginationProps);
  const [loading, setLoading] = useState(true);
  const [formParams, setFormParams] = useState({});
  const [visible, setVisible] = useState(false);
  const [editMode, setEditMode] = useState(EditMode.Create);
  const [selectRecord, setSelectRecord] = useState<ModelResponse>();
  useEffect(() => {
    fetchData();
  }, [pagination.current, pagination.pageSize, formParams]);

  function fetchData() {
    const { current, pageSize } = pagination;
    setLoading(true);
    instance
      .post('/api/model/page', {
        pager: {
          pageNumber: current,
          pageSize
        },
        query: {
          ...formParams
        }
      })
      .then((res) => {
        if (res.data.code === 200) {
          setData((res.data.data || []).map(it => {
            return {
              ...it,
              privateParameters: (it.parameters || []).filter(iit => !!!iit.common),
              publicParameters: (it.parameters || []).filter(iit => !!iit.common)
            };
          }));
          setPagination({
            ...pagination,
            current,
            pageSize,
            total: res.data.total
          });
        }
      }).finally(() => {
      setLoading(false);
    });
  }

  function onDeleteRecord(id: number) {
    setLoading(true);
    instance
      .post('/api/model/delete', { id: id })
      .then((res) => {
        if (res.data.code === 200) {
          Notification.success({
            title: res.data.message,
            content: ''
          });
        } else {
          Notification.error({
            title: res.data.message,
            content: res.data.data
          });
        }
      })
      .finally(() => {
        setLoading(false);
        fetchData();
      });
  }


  function onCreateRecord(record: ModelResponse) {
    setSelectRecord(record);
    setEditMode(EditMode.Create);
    setVisible(true);
  }

  function onUpdateRecord(record: ModelResponse) {
    setSelectRecord(record);
    setEditMode(EditMode.Update);
    setVisible(true);
  }

  return (
    <Card>
      <SearchForm onSubmit={it => setFormParams(it)} onReset={() => setFormParams({})} />
      <Row justify={'space-between'}>
        <Space>
          <Button type="primary" icon={<IconPlus />} onClick={() => onCreateRecord(null)}>
            {t['button.create']}
          </Button>
        </Space>
      </Row>
      <Table
        style={{ marginTop: '1rem' }}
        rowKey={record => record.id}
        loading={loading}
        onChange={({ current, pageSize }) => setPagination({ ...pagination, current, pageSize })}
        pagination={pagination}
        columns={[
          {
            title: t['columns.id'],
            dataIndex: 'id'
          },
          {
            title: t['columns.name'],
            dataIndex: 'name'
          },
          {
            title: t['columns.code'],
            dataIndex: 'code'
          },
          {
            title: t['columns.parameters.public'],
            dataIndex: 'publicParameters',
            render: (value: ParameterResponse[]) => {
              const list = (value || []).map(it => <Tag key={'tag_public_' + it.id}
                                                        style={{ marginRight: 10 }}
                                                        color="green">{it.name}</Tag>);
              if (list.length > 3) {
                list[3] = <span key={'tag_public_' + value[3].id}>...</span>;
              }
              return list.slice(0, 4);
            }
          },
          {
            title: t['columns.parameters.private'],
            dataIndex: 'privateParameters',
            render: (value: ParameterResponse[]) => {
              const list = (value || []).map(it => <Tag key={'tag_private_' + it.id}
                                                        style={{ marginRight: 10 }}
                                                        color="green">{it.name}</Tag>);
              if (list.length > 3) {
                list[3] = <span key={'tag_private_' + value[3].id}>...</span>;
              }
              return list.slice(0, 4);
            }
          },
          {
            title: t['columns.enabled'],
            dataIndex: 'enabled',
            render: (value: boolean) => {
              return value === true
                ? <Badge status="success" text={resolveEnabledName(value)}></Badge>
                : <Badge status="error" text={resolveEnabledName(value)}></Badge>;
            }
          },
          {
            title: t['columns.remark'],
            dataIndex: 'remark'
          },
          {
            title: t['columns.operations'],
            headerCellStyle: { paddingLeft: '15px' },
            render: (_, record: ModelResponse) => {
              return <TableOperationButtonGroup
                record={record}
                onCreate={() => onCreateRecord(record)}
                onUpdate={() => onUpdateRecord(record)}
                onDelete={() => onDeleteRecord(record?.id)}
              />;
            }
          }
        ]}
        data={data}
      />
      <ModelDrawer visible={visible} toggleVisible={setVisible}
                   mode={editMode} record={selectRecord} onFinish={fetchData} />
    </Card>
  );
};

export default ModelPage;